package com.tju.resource.server.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mysql.cj.xdevapi.JsonArray;
import com.mysql.cj.xdevapi.JsonValue;
import com.tju.resource.common.ServiceException;
import com.tju.resource.mapper.*;
import com.tju.resource.tool.result.Result;
import com.tju.resource.tool.result.ResultEnum;
import com.tju.resource.tool.result.ResultUtil;
import com.tju.resource.model.*;
import com.tju.resource.tool.tool.ClientParameters;
import com.tju.resource.server.SysRoleService;
import com.tju.resource.tool.tool.QuickQuery;
import com.tju.resource.tool.tool.StringUtil;
import jodd.util.ArraysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;

import static com.tju.resource.tool.tool.ListUtils.*;

/**
 * 角色业务实现
 *
 * @Author CLS
 * @Date 2021/12/31 14:22
 */
@Slf4j
@Service
public class SysRoleServiceImpl implements SysRoleService {

    @Autowired
    SysRoleMapper mapper;

    @Autowired
    SysUserMapper uMapper;

    @Autowired
    SysUserRoleMapper urMapper;

    @Autowired
    SysRolePermissionMapper rpMapper;

    @Autowired
    DocContentMapper dcMapper;

    @Autowired
    DocUserPermMapper dupMapper;

    @Autowired
    SysPermissionMapper spMapper;

    @Override
    public SysRole getCharacter(Long cId) {
        return mapper.selectById(cId);
    }

    @Override
    public Result<Object> getCharacterAll(ClientParameters parameter) {
        if (!StringUtils.isBlank(parameter.getTwo())) {
            SysUser user = QuickQuery.byOne(uMapper, "username", parameter.getTwo());

            if (null != user) {
                List<SysRole> sysRoles = byUser(user.getUsername());
                AtomicBoolean isManager = new AtomicBoolean(false);

                sysRoles.forEach(role -> {
                    if (role.getGrade() == 0L) {
                        isManager.set(true);
                    }
                });

                if (isManager.get()) {
                    parameter.setFour("true");
                } else {
                    parameter.setFour("false");
                }

                try {
                    Page<SysRole> page = new Page<>(parameter.getPage(), parameter.getLimit());
                    IPage<SysRole> iPage = mapper.getCharacterAll(page, parameter);
                    List<SysRole> records = iPage.getRecords();

                    records.forEach(this::setSrRoles);

                    return ResultUtil.success(ResultEnum.SUCCESS, records, iPage.getTotal());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                return ResultUtil.error(ResultEnum.UNKONW_ERROR, "用户名不可为空!");
            }

        }

        return null;
    }

    @Override
    @Transactional
    public Long addCharacter(Map<String, String> params) {
        SysRole sysRole = new SysRole();
        JSONArray roles = new JSONArray();
        StringBuilder halfRoles = new StringBuilder();
        JSONArray half = JSONUtil.parseArray(params.get("half"));

        sysRole.setName(params.get("name"));
        sysRole.setRemark(params.get("remark"));

        mapper.addCharacter(sysRole);

        if (null != params.get("half") && null != params.get("full")) {
            half.forEach(e -> halfRoles.append(e).append(","));
            roles.addAll(JSONUtil.parseArray(params.get("full")));
            roles.addAll(half);

            if (halfRoles.length() != 0) {
                if (halfRoles.reverse().charAt(0) == ',') {
                    halfRoles.deleteCharAt(0).reverse();
                }
            }

            remDup(roles);
            batchIns(roles, sysRole.getId(), halfRoles.toString(), half);
            batchRoleDoc(sysRole.getId(), roles);
        }

        return sysRole.getId();
    }

    @Override
    @Transactional
    public int updCharacter(Map<String, String> params) {
        SysRole sysRole = mapper.selectById(Integer.parseInt(params.get("id")));
        int updRes;
        JSONArray roles = new JSONArray();
        StringBuilder halfRoles = new StringBuilder();
        JSONArray half = JSONUtil.parseArray(params.get("half"));
        JSONArray newId = JSONUtil.parseArray(params.get("newId"));
        JSONArray cancel = JSONUtil.parseArray(params.get("cancel"));

        sysRole.setName(params.get("name"));
        sysRole.setRemark(params.get("remark"));
        sysRole.setUpdateDate(new Date());

        updRes = mapper.updateById(sysRole);

        if (null != params.get("half") && null != params.get("full")) {
            roles.addAll(JSONUtil.parseArray(params.get("full")));
            half.forEach(e -> halfRoles.append(e).append(","));
            roles.addAll(half);

            if (halfRoles.length() != 0) {
                if (halfRoles.reverse().charAt(0) == ',') {
                    halfRoles.deleteCharAt(0).reverse();
                }
            }

            remDup(roles);
//            batchDel(sysRole.getId(), cancel);
            batchDelSRP(sysRole.getId());
            batchDelDoc(sysRole.getId(), cancel);
//            batchHalfRoles(sysRole.getId(), halfRoles.toString());
            batchIns(roles, sysRole.getId(), halfRoles.toString(), half);
            batchRoleDoc(sysRole.getId(), newId);
        }

        return updRes;
    }

    @Transactional
    @Override
    public int delCharacter(Map<String, String> params) {
        Long roleId = Long.parseLong(params.get("id"));
        int delRes;

        if (getUsersRoles(roleId) == 0) {
            delRes = mapper.deleteById(roleId);
            batchDelSRP(roleId);
            batchDelRoleDoc(roleId);
        } else {
            throw new ServiceException("该角色已被使用！");
        }
        return delRes;
    }

    @Transactional
    public void batchIns(JSONArray roles, Long roleId, String halfRoles, JSONArray halfArr) {
        List<SysRolePermission> cRoles = new ArrayList<>();
        boolean f = false;

        remDup(roles);
        for (Object role : roles) {
            Long rId = Long.parseLong(role + "");
            SysRolePermission srp = new SysRolePermission();

            srp.setRoleId(roleId);
            srp.setPermissionId(rId);
            srp.setIsHalf("false");

            if (!f) {
                srp.setHalfRoles(halfRoles);
                f = true;
            }

            halfArr.forEach(ele -> {
                if (StringUtils.equals(ele + "", rId + "")) {
                    srp.setIsHalf("true");
                }
            });

            cRoles.add(srp);
        }

        cRoles.forEach(rpMapper::insert);
    }

    @Transactional
    public void batchRoleDoc(long roleId, JSONArray roles) {
        String arr[] = new String[roles.size()];

        for (int i2 = 0; i2 < roles.size(); i2++) {
            arr[i2] = roles.get(i2).toString();
        }

        if (0 != arr.length) {
            List<SysPermission> list = QuickQuery.list(spMapper, "id", arr);
            String sarr[] = new String[list.size()];
            List<DocContent> cList;

            for (int i2 = 0; i2 < list.size(); i2++) {
                sarr[i2] = list.get(i2).getCode();
            }
            cList = QuickQuery.list(dcMapper, "feature_code", sarr);

            if (0 != cList.size()) {
                String codes[] = new String[cList.size()];
                List<SysPermission> permissions;

                for (int i2 = 0; i2 < cList.size(); i2++) {
                    codes[i2] = cList.get(i2).getFeatureCode();
                }
                permissions = QuickQuery.list(spMapper, "code", codes);

                cList.forEach(v -> {
                    DocUserPerm docUserPerm = new DocUserPerm();
                    AtomicLong perId = new AtomicLong(0L);

                    for (SysPermission permission : permissions) {
                        if (StringUtils.equals(v.getFeatureCode(), permission.getCode())) {
                            perId.set(permission.getParentId());
                        }
                    }

                    docUserPerm.setRolePerId(Integer.parseInt(roleId + ""));
                    docUserPerm.setDocContId(Integer.parseInt(v.getId() + ""));
                    docUserPerm.setParentId(Integer.parseInt("" + perId.get()));

                    dupMapper.insert(docUserPerm);
                });
            }
        }
    }

    @Transactional
    public void batchDelDoc(long roleId, JSONArray roles) {
        String arr[] = new String[roles.size()];

        for (int i2 = 0; i2 < roles.size(); i2++) {
            arr[i2] = roles.get(i2).toString();
        }

        if (0 != arr.length) {
            List<SysPermission> list = QuickQuery.list(spMapper, "id", arr);
            String sarr[] = new String[list.size()];
            List<DocContent> cList;
            String docIds[];

            for (int i2 = 0; i2 < list.size(); i2++) {
                sarr[i2] = list.get(i2).getCode();
            }

            if (0 != sarr.length) {
                cList = QuickQuery.list(dcMapper, "feature_code", sarr);

                if (0 != cList.size()) {
                    docIds = new String[cList.size()];

                    for (int i2 = 0; i2 < cList.size(); i2++) {
                        docIds[i2] = cList.get(i2).getId() + "";
                    }

                    QueryWrapper<DocUserPerm> wrapper = QuickQuery.wrapper(dupMapper, "doc_cont_id", docIds).eq("role_per_id", roleId);
                    dupMapper.delete(wrapper);
                }
            }
        }
    }

    @Transactional
    public void batchDelRoleDoc(long roleId) {
        QueryWrapper<DocUserPerm> wrapper = new QueryWrapper<>();
        wrapper.eq("role_per_id", roleId);
        dupMapper.delete(wrapper);
    }

    @Transactional
    public void batchDelSRP(Long roleId) {
        QueryWrapper<SysRolePermission> wrapper = new QueryWrapper<>();
        wrapper.eq("role_id", roleId);
        rpMapper.delete(wrapper);
    }

    @Override
    public boolean hasRoleName(String roleName) {
        return 0 != QuickQuery.list(mapper, QuickQuery.params().putOnce("name", roleName)).size();
    }

    @Override
    public List<SysRole> byUser(String username) {
        return mapper.byUser(username);
    }

    public JSONArray getSrRoles(Long roleId) {
        QueryWrapper<SysRolePermission> query = new QueryWrapper<>();
        List<SysRolePermission> queryResult;
        JSONArray ja = new JSONArray();

        query.eq("role_id", roleId);
        queryResult = rpMapper.selectList(query);
        queryResult.forEach(ele -> {
            if (!StringUtils.equals("true", ele.getIsHalf())) {
                ja.add(ele.getPermissionId());
            }
        });

        return ja;
    }

    public JSONArray getSrHalf(Long roleId) {
        QueryWrapper<SysRolePermission> query = new QueryWrapper<>();
        AtomicReference<JSONArray> result = new AtomicReference<>(JSONUtil.parseArray("[]"));

        query.eq("role_id", roleId);

        rpMapper.selectList(query).forEach(ele -> {
            if (!StringUtils.isBlank(ele.getHalfRoles())) {
                String[] split = ele.getHalfRoles().split(",");
                Integer[] iarr = new Integer[split.length];

                for (int i2 = 0; i2 < split.length; i2++) {
                    if (!StringUtils.isBlank(split[i2])) {
                        iarr[i2] = Integer.parseInt(split[i2]);
                    }
                }

                for (Object o : JSONUtil.parseArray(Arrays.asList(iarr))) {
                    result.get().add(o);
                }
            }
        });

        remDup(result.get());
        return result.get();
    }

    public void setSrRoles(SysRole sr) {
        sr.setRoles(getSrRoles(sr.getId()));
        sr.setHalfRoles(getSrHalf(sr.getId()));
    }

    public int getUsersRoles(Long roleId) {
        QueryWrapper<SysUserRole> query = new QueryWrapper<>();
        List<SysUserRole> result;

        query.eq("role_id", roleId);
        result = urMapper.selectList(query);

        return null == result ? 0 : result.size();
    }

    public void batchDel(Long roleId, JSONArray roles) {
        String vals[] = new String[roles.size()];

        for (int i2 = 0; i2 < roles.size(); i2++) {
            if (!StringUtils.isBlank(roles.get(i2) + "") && !StringUtils.equals(roles.get(i2) + "", "null")) {
                vals[i2] = roles.get(i2) + "";
            }
        }

        if (0 != vals.length) {
            QueryWrapper<SysRolePermission> wrapper = QuickQuery.wrapper(rpMapper, "permission_id", vals).eq("role_id", roleId);
            rpMapper.delete(wrapper);
        }
    }

    public void batchHalfRoles(Long roleId, String halfRoles) {
        String roles[] = halfRoles.split(",");
        List<String> rList = Arrays.asList(roles);
        List<SysRolePermission> list = rpMapper.selectList(QuickQuery.wrapper(rpMapper, "permission_id", roles).eq("roleId", roleId));

        list.forEach(role -> {
            if (rList.contains(role.getRoleId() + "")) {
                role.setIsHalf("true");
            }
            role.setHalfRoles(halfRoles);
        });

    }
}
